package com.atguigu.gmall.product.service.impl;

import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.product.service.BloomService;
import com.atguigu.gmall.product.service.SkuInfoService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;

import java.util.Arrays;


@Slf4j
@Service
public class BloomServiceImpl implements BloomService {

    @Autowired
    SkuInfoService skuInfoService;

    @Autowired
    RedissonClient redisson;

    @Autowired
    StringRedisTemplate redisTemplate;

    @Override
    public void resetBloom(String bloomSkuid) {
        //TODO 如何重建布隆？
        //删了重做？
        // 高速换胎
        //如何尽量缩短布隆不可用时间。 布隆重置期间不可用
        //1、创建一个新的布隆。保存所有数据
        RBloomFilter<Object> filter = redisson.getBloomFilter(bloomSkuid + "-new");
        if (!filter.isExists()) {
            log.info("正在重置布隆....新布隆创建中....");
            filter.tryInit(1000000, 0.000001);
            skuInfoService.getAllSkuId().stream().forEach(item -> {
                filter.add(item);
            });
            filter.add(99L);
        }

        //skuid-bloom-new
        //{skuid-bloom-new}:config

        //skuid-bloom
        //{skuid-bloom}:config
        //2、删除旧布隆
//        RBloomFilter<Object> oldBloom = redisson.getBloomFilter(RedisConst.BLOOM_SKUID);
//        oldBloom.delete();

        //3、改名
//        filter.rename(RedisConst.BLOOM_SKUID);

        //4、原子操作  (要删除的key(skuid-bloom)，把更名的key(skuid-bloom-new)，改为要删除的key)
        String script = "redis.call(\"del\",KEYS[1]);" +
                "redis.call(\"del\",\"{\"..KEYS[1]..\"}:config\");" +
                "redis.call(\"rename\",KEYS[2],KEYS[1]);" +
                "redis.call(\"rename\",\"{\"..KEYS[2]..\"}:config\",\"{\"..KEYS[1]..\"}:config\"); return 0;";

        //RENAME key newkey
        //原子换轮胎
        redisTemplate.execute(new DefaultRedisScript<>(script, Long.class),
                Arrays.asList(bloomSkuid, bloomSkuid + "-new"));
        log.info("布隆更换完成....新布隆上线....");
        
    }
    /**
     * skuid-bloom、skuid-bloom-new
     * redis.call("del",KEYS[1])；
     * redis.call("del","{"+KEYS[1]+"}:config");
     * redis.call("rename",KEYS[2],KEYS[1]);
     * redis.call("rename","{"+KEYS[2]+"}:config","{"+KEYS[1]+"}:config")
     */
}
